//
//  main.cpp
//  word2vec
//
//  Created by LazyLie on 14-8-11.
//  Copyright (c) 2014年 NLP Group. All rights reserved.
//

#include "word2vec.h"
#include <iostream>
#include <vector>
#include <string>
#include <utility>
#include <cmath>
#include <fstream>
#include <algorithm>

double dis(const word2vec::vec_t &a, const word2vec::vec_t &b) {
    if (a.size() != b.size()) {
        std::cout << "Fail: dis receives 2 vectors with different size.";
        exit(0);
    }
    double aa = 0, bb = 0, c = 0;
    for (int i = 0; i < a.size(); i++) {
        aa += a[i] * a[i];
        bb += b[i] * b[i];
        c += a[i] * b[i];
    }
    return c / sqrt(aa) / sqrt(bb);
}

int main(int argc, const char * argv[]) {
    
    word2vec model;
    model.init("text8");
    model.train();
    word2vec::result_t result = model.get_result();
    
    std::ofstream writer("vector.txt");
    for (auto entry : result) {
        writer << entry.first;
        for (auto x : entry.second)
            writer << " " << x;
        writer << std::endl;
    }
    writer.close();
    
    /*
    word2vec::result_t result;
    std::ifstream vr("vectors.txt");
    std::string ss;
    while (vr >> ss) {
        word2vec::vec_t vec(50);
        for (int i = 0; i < 50; i++)
            vr >> vec[i];
        result.push_back(std::make_pair(ss, vec));
    }
    */
    std::ifstream reader("question.txt");
    std::string s[4], type;
    int correct = 0, total = 0, c1 = 0, t1 = 0;
    while (reader >> s[0]) {
        double best = -1;
        std::string bests;

        if (s[0] == ":") {
            if (total)
                std::cout << type << ": " << c1 << " / " << t1 << std::endl;
            reader >> type;
            c1 = t1 = 0;
            continue;
        } else
            reader >> s[1] >> s[2] >> s[3];
        word2vec::vec_t vec[4], tar;
        for (auto &str : s)
            for (auto &ch : str)
                if ('A' <= ch && ch <= 'Z')
                    ch += 'a' - 'A';
        for (auto &entry : result)
            for (int i = 0; i < 4; i++)
                if (entry.first == s[i])
                    vec[i] = entry.second;
        bool mark = 1;
        for (auto &v : vec)
            if (v.size() == 0)
                mark = 0;
        if (!mark) continue;
        tar.resize(vec[0].size());
        for (int i = 0; i < tar.size(); i++)
            tar[i] = vec[1][i] - vec[0][i] + vec[2][i];
        for (auto &entry : result) {
            if (entry.first == s[0] || entry.first == s[1] || entry.first == s[2])
                continue;
            double tmp = dis(entry.second, tar);
            if (tmp > best) {
                best = tmp;
                bests = entry.first;
            }
        }
        if (bests == s[3]) {
            correct++;
            c1++;
        }
        total++;
        t1++;
    }
    std::cout << type << ": " << c1 << " / " << t1 << std::endl;
    std::cout << (double)correct / total << std::endl;
    
    /*
     while (std::cin >> s[0] >> s[1] >> s[2]) {
     word2vec::vec_t vec[3], tar;
     for (auto &str : s) {
     for (auto &ch : str) {
     if ('A' <= ch && ch <= 'Z') {
     ch += 'a' - 'A';
     }
     }
     }
     for (auto &entry : result) {
     for (int i = 0; i < 3; i++) {
     if (entry.first == s[i]) {
     vec[i] = entry.second;
     }
     }
     }
     bool mark = 1;
     for (auto &v : vec) {
     if (v.size() == 0) {
     mark = 0;
     }
     }
     if (!mark) continue;
     
     tar.resize(vec[0].size());
     
     for (int i = 0; i < tar.size(); i++) {
     tar[i] = vec[1][i] - vec[0][i] + vec[2][i];
     }
     
     std::multimap<double, std::string> near;
     
     for (auto &entry : result) {
     near.insert(std::make_pair(dis(entry.second, tar), entry.first));
     }
     
     auto ii = near.rbegin();
     for (int i = 0; i < 10 && ii != near.rend(); i++, ii++) {
     std::cout << ii->second << std::endl;
     }
     }
     */
}

